package com.example.myaccount.component;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.example.myaccount.constant.MyConst;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class PieView extends View {

    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    private Path mPath = new Path();

    private float mHeight;
    private float mWidth;

    private float mSectorsX;
    private float mSectorsY;

    private static final float mRadius = 300f; // 半径
    private float mSkewingLength = 10f; // 偏移长度

    private List<SectorsData> mSectorsDataList; // 扇形数据
    private List<LinesData> mLinesDataList; // 线数据
    private List<TextsData> mTextsDataList; // 文字数据

    // 模拟数据
    private Map<String, Double> mDataMap = new LinkedHashMap<>(); // 需要按顺序，所以用 LinkedHashMap

    public Map<String, Double> getmDataMap() {
        return mDataMap;
    }

    public void setmDataMap(Map<String, Double> mDataMap) {
        this.mDataMap = mDataMap;
    }

//    {
//        mDataMap.put("Froyo", 2f);
//        mDataMap.put("Gingerbread", 6f);
//        mDataMap.put("ice Cream Sandwich", 5f);
//        mDataMap.put("Jelly Bean", 50f);
//        mDataMap.put("KitKat", 80f);
//        mDataMap.put("Lollipop", 110f);
//        mDataMap.put("Marshmallow", 40f);
//    }


    // 模拟颜色
    private List<Integer> mColors = new ArrayList<>();
    {
        mColors.add(Color.CYAN);
        mColors.add(Color.MAGENTA);
        mColors.add(Color.GRAY);
        mColors.add(Color.GREEN);
        mColors.add(Color.BLUE);
        mColors.add(Color.RED);
        mColors.add(Color.YELLOW);
        mColors.add(Color.BLACK);
        mColors.add(Color.WHITE);
    }

    public PieView(Context context) {
        super(context);
    }

    public PieView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public PieView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // 获取当前view的宽高
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();

        // 扇形中心点
        mSectorsX = mWidth / 2;
        mSectorsY = mHeight / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 综合练习
        // 练习内容：使用各种 Canvas.drawXXX() 方法画饼图
        drawSectors(canvas);
        drawLines(canvas);
        drawTexts(canvas);
    }

    /**
     * 画文字
     **/
    private void drawTexts(Canvas canvas) {
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.BLACK);
        mPaint.setTextSize(30f);

        mTextsDataList = calculateTextsDatas();
        TextsData textsData;
        for (int i = 0; i < mTextsDataList.size(); i++) {
            textsData = mTextsDataList.get(i);
            mPaint.setTextAlign(textsData.PAINT_ALIGN);
            canvas.drawText(textsData.name.split(" ")[0], textsData.startX, textsData.startY, mPaint);
            canvas.drawText(textsData.name.split(" ")[1],mLinesDataList.get(i).turnX,mLinesDataList.get(i).turnY-5,mPaint);
        }
        mPaint.setTextAlign(Paint.Align.CENTER); // 设置坐标点在字符的中心
        mPaint.setTextSize(60f);
//        canvas.drawText("饼图", mSectorsX, mSectorsY + mRadius / 2 * 3, mPaint);
    }

    /**
     * 计算各文字的坐标
     **/
    private List<TextsData> calculateTextsDatas() {

        List<TextsData> textsDataList = new ArrayList<>();

        for (int i = 0; i < mDataMap.size(); i++) {
            TextsData textsData = new TextsData();
            LinesData linesData = mLinesDataList.get(i);
            // 根据线的终点计算文字的坐标
            if (linesData.middleAngle > 90 && linesData.middleAngle < 270) {
                textsData.startX = linesData.endX - 10;
                textsData.PAINT_ALIGN = Paint.Align.RIGHT;
            } else {
                textsData.startX = linesData.endX + 10;
                textsData.PAINT_ALIGN = Paint.Align.LEFT;
            }
            textsData.startY = linesData.turnY;

            textsDataList.add(textsData);
        }

        List<String> nameList = new ArrayList(mDataMap.keySet());
//        Log.d(MyConst.TAG,nameList.toString());
        for (int i = 0; i < nameList.size(); i++) {
            textsDataList.get(i).name = nameList.get(i);
        }

        return textsDataList;
    }

    /**
     * 文字数据类
     **/
    private class TextsData {
        Paint.Align PAINT_ALIGN;
        String name;
        float startX;
        float startY;
    }

    /**
     * 画线
     **/
    private void drawLines(Canvas canvas) {
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(3f);
        mPaint.setColor(Color.BLACK);

        mLinesDataList = calculateLinesDatas();
        LinesData linesData;
        for (int i = 0; i < mLinesDataList.size(); i++) {
            linesData = mLinesDataList.get(i);
            mPath.moveTo(linesData.startX, linesData.startY);
            mPath.lineTo(linesData.turnX, linesData.turnY);
            mPath.lineTo(linesData.endX, linesData.endY);
            canvas.drawPath(mPath, mPaint);
        }
    }

    /**
     * 计算各线的 Path
     **/
    private List<LinesData> calculateLinesDatas() {

        List<LinesData> linesDataList = new ArrayList<>();

        for (int i = 0; i < mDataMap.size(); i++) {
            LinesData linesData = new LinesData();
            SectorsData sectorsData = mSectorsDataList.get(i);

            // 线的起点
            float startX;
            float startY;
            startX = (float) (mRadius * Math.cos(sectorsData.middleAngle * Math.PI / 180));
            startY = (float) (mRadius * Math.sin(sectorsData.middleAngle * Math.PI / 180));
            linesData.startX = sectorsData.sectorsX + startX;
            linesData.startY = sectorsData.sectorsY + startY;

            // 线的转折点
            float turnX;
            float turnY;
            turnX = (float) ((mRadius + 50) * Math.cos(sectorsData.middleAngle * Math.PI / 180));
            turnY = (float) ((mRadius + 50) * Math.sin(sectorsData.middleAngle * Math.PI / 180));
            linesData.turnX = sectorsData.sectorsX + turnX;
            linesData.turnY = sectorsData.sectorsY + turnY;

            // 线的终点
            if (sectorsData.middleAngle > 90 && sectorsData.middleAngle < 270) {
                linesData.endX = mSectorsX - mRadius - 100;
            } else {
                linesData.endX = mSectorsX + mRadius + 100;
            }
            linesData.endY = linesData.turnY;
            linesData.middleAngle = sectorsData.middleAngle;

            linesDataList.add(linesData);
        }

        return linesDataList;
    }

    /**
     * 线数据类
     **/
    private class LinesData {
        float startX;
        float startY;
        float turnX;
        float turnY;
        float endX;
        float endY;
        float middleAngle;
    }

    /**
     * 画扇形
     **/
    private void drawSectors(Canvas canvas) {
        mPaint.setStyle(Paint.Style.FILL); // 填充模式

        mSectorsDataList = calculateSectorsDatas();
        SectorsData sectorsData;
        for (int i = 0; i < mSectorsDataList.size(); i++) {
            sectorsData = mSectorsDataList.get(i);
            mPaint.setColor(mColors.get(i));
            canvas.drawArc(sectorsData.left, sectorsData.top, sectorsData.right, sectorsData.bottom, sectorsData.startAngle, sectorsData.sweepAngle, true, mPaint);
        }
    }

    /**
     * 计算各扇形的坐标、角度
     **/
    private List<SectorsData> calculateSectorsDatas() {
        List<SectorsData> sectorsDataList = new ArrayList<>();
        float startAngle = 0; // 开始角度
        float sweepAngle; // 扇形角度
        float sum = 0;
        for (String key : mDataMap.keySet()) {
            sum += mDataMap.get(key);
        }
        float maxValue = (float) getMaxValue(mDataMap);
        for (String key : mDataMap.keySet()) {
            // 突出最大的块
            if (mDataMap.get(key) == maxValue) {
                mSkewingLength = 30f;
            } else {
                mSkewingLength = 10f;
            }
            sweepAngle = (float) (mDataMap.get(key) / sum) * 360;
            SectorsData sectorsData = calculateDirectionCoord(startAngle, sweepAngle);
            sectorsData.startAngle = startAngle;
            sectorsData.sweepAngle = sweepAngle;
            sectorsDataList.add(sectorsData);
            startAngle += sectorsData.sweepAngle;
        }
        return sectorsDataList;
    }

    /**
     * 根据扇形角度计算扇形偏移方向及最终坐标
     */
    private SectorsData calculateDirectionCoord(float startAngle, float sweepAngle) {

        SectorsData sectorsData = new SectorsData();
        sectorsData.middleAngle = (startAngle + sweepAngle / 2); // 中间角度，用于计算偏移方向角度

        float skewingX; // 偏移x量
        float skewingY; // 偏移Y量
        // 已经斜边和角度: 角度的对边 = 斜边*sin角度 ; 角度邻边 = 斜边*cos角度
        // TODO : 角度转弧度 π/180×角度 【Math.cos、Math.sin参数是弧度 ！】
        skewingX = (float) (mSkewingLength * Math.cos(sectorsData.middleAngle * Math.PI / 180));
        skewingY = (float) (mSkewingLength * Math.sin(sectorsData.middleAngle * Math.PI / 180));

        sectorsData.left = mSectorsX - mRadius + skewingX;
        sectorsData.top = mSectorsY - mRadius + skewingY;
        sectorsData.right = mSectorsX + mRadius + skewingX;
        sectorsData.bottom = mSectorsY + mRadius + skewingY;

        sectorsData.sectorsX = mSectorsX + skewingX;
        sectorsData.sectorsY = mSectorsY + skewingY;

        return sectorsData;
    }

    /**
     * 获取 map中 value的最大值
     *
     * @return
     * */
    private double getMaxValue(Map<String, Double> map) {
        Double max = 0d;
        for (Map.Entry<String, Double> entry : map.entrySet()) {
            if (entry.getValue() > max) {
                max = entry.getValue();
            }
        }
        return max;
    }

    /**
     * 扇形数据类
     **/
    private class SectorsData {
        float left;
        float top;
        float right;
        float bottom;
        float startAngle;
        float sweepAngle;
        float middleAngle;
        float sectorsX;
        float sectorsY;
    }
}